<script>
import draggable from "vuedraggable";
import render from "./custom/render";
import dynamicTable from "./dynamic/dynamicTable";
import dynamicTableItem from "./dynamic/dynamicTableItem";
import fancyTable from "./table/fancyTable";
import fancyTableItem from "./table/fancyTableItem";
import { getSimpleId } from "./utils/IdGenerate";
import { tableAllowedItems, dynamicTableAllowedItems } from "./custom/formConf";

/**
 * 动态表单允许增加的组件列表
 */
const components = {
  itemBtns(h, element, parent) {
    const { copyItem, deleteItem } = this.$listeners;
    return [
      <span
        class="drawing-item-copy"
        title="复制"
        onClick={(event) => {
          copyItem(element, parent);
          event.stopPropagation();
        }}
      >
        <i class="el-icon-copy-document" />
      </span>,
      <span
        class="drawing-item-delete"
        title="删除"
        onClick={(event) => {
          deleteItem(element, parent);
          event.stopPropagation();
        }}
      >
        <i class="el-icon-delete" />
      </span>,
    ];
  },
};

const layouts = {
  colItem(h, element, parent) {
    let className =
      this.activeItem.id === element.id
        ? "drawing-item drawing-form-item active-from-item"
        : "drawing-item drawing-form-item";
    let labelWidth = element.labelWidth ? `${element.labelWidth}px` : null;
    let itemWidth = element.width ? `width:${element.width}%;` : null;
    const { onActiveItemChange } = this.$listeners;
    return (
      <el-col
        class={className}
        span={element.span}
        compType={element.compType}
        nativeOnClick={(event) => {
          onActiveItemChange(element);
          event.stopPropagation();
        }}
      >
        <span class="component-name component-id">{element.id}</span>
        <el-form-item
          label={element.showLabel ? element.label : ""}
          label-width={labelWidth}
          required={element.required}
          style={itemWidth}
        >
          <render
            key={element.id}
            conf={element}
            onInput={(event) => {
              this.$set(element, "value", event);
            }}
          />
        </el-form-item>
        {components.itemBtns.apply(this, arguments)}
      </el-col>
    );
  },

  rowItem(h, element) {
    const { onActiveItemChange } = this.$listeners;
    const className =
      this.activeItem.id === element.id
        ? "drawing-item drawing-row-item active-from-item"
        : "drawing-item drawing-row-item";
    return (
      <el-col class={className} compType={element.compType}>
        <el-row
          gutter={element.gutter}
          nativeOnClick={(event) => {
            onActiveItemChange(element);
            event.stopPropagation();
          }}
        >
          <span class="component-name">{element.id}</span>
          <div class="drag-wrapper" style="padding-left: 5px; padding-right: 5px;">
            {element.columns.map((item, index) => {
              return (
                <el-col class="drag-col-wrapper" span={item.span}>
                  <draggable
                    class="drag-wrapper row-drag"
                    v-model={item.list}
                    animation="100"
                    group="componentsGroup"
                    onAdd={(e) => {
                      this.handlerAdd(e, item, element);
                    }}
                  >
                    {item.list.map((obj, objIndex) => {
                      return (
                        <el-row class="test-item">
                          {renderChildren.call(this, h, obj, element)}
                        </el-row>
                      );
                    })}
                  </draggable>
                </el-col>
              );
            })}
          </div>
        </el-row>
        {components.itemBtns.call(this, h, element)}
      </el-col>
    );
  },

  tableItem(h, element) {
    let className = "";
    className =
      this.activeItem.id === element.id
        ? "drawing-item drawing-row-item active-from-item"
        : "drawing-item drawing-row-item";
    const { onActiveItemChange } = this.$listeners;
    return (
      <el-col
        class={className}
        nativeOnClick={(event) => {
          onActiveItemChange(element);
          event.stopPropagation();
        }}
      >
        <span class="component-name" style="margin-bottom:15px">
          {element.id}
        </span>
        <fancy-table
          layoutArray={element.layoutArray}
          tdStyle={element.tdStyle}
          align={element.align}
          valign={element.valign}
          width={element.width}
          height={element.height}
          border={element.border}
          borderColor={element.borderColor}
          borderCollapse={element.borderCollapse}
          cellpadding={element.cellpadding}
          cellspacing={element.cellspacing}
          onSelectItem={(item) => {
            onActiveItemChange(item);
          }}
          scopedSlots={{
            default: (item) => {
              return (
                <draggable
                  tag="div"
                  class="table__content row-drag"
                  v-model={item.td.columns}
                  animation="100"
                  group="componentsGroup"
                  onAdd={(e) => {
                    this.handlerTableAdd(e, item.td);
                    e.stopPropagation();
                  }}
                >
                  {item.td.columns.map((obj) => {
                    return renderChildren.call(this, h, obj, item.td);
                  })}
                </draggable>
              );
            },
          }}
        />
        {components.itemBtns.call(this, h, element)}
      </el-col>
    );
  },

  dynamicItem(h, element) {
    let className = "";
    className =
      this.activeItem.id === element.id
        ? className + "drawing-item drawing-row-item active-from-item"
        : className + "drawing-item  drawing-row-item";
    const { onActiveItemChange } = this.$listeners;
    return (
      <el-col class={className}>
        <dynamic-table
          conf={element}
          activeItem={this.activeItem}
          nativeOnClick={(event) => {
            onActiveItemChange(element);
            event.stopPropagation();
          }}
        >
          <draggable
            tag="div"
            class="dynamic-table__content row-drag"
            ghost-class="dynamicGhost"
            v-model={element.columns}
            animation="100"
            group="componentsGroup"
            onAdd={(e) => {
              this.handlerDynamicAdd(e, element);
            }}
          >
            {element.columns.map((item, index) => {
              return (
                <dynamic-table-item
                  item={item}
                  activeItem={this.activeItem}
                  onSelectItem={(evt, item) => {
                    onActiveItemChange(item);
                    evt.stopPropagation();
                  }}
                  onCopyItem={(evt) => {
                    this.handlerCopyItem(evt, element, index);
                    evt.stopPropagation();
                  }}
                  onDeleteItem={(evt) => {
                    this.handlerDeleteItem(evt, element, index);
                    evt.stopPropagation();
                  }}
                />
              );
            })}
          </draggable>
        </dynamic-table>
        {components.itemBtns.call(this, h, element)}
      </el-col>
    );
  },
};

/**
 * 生成row的子选项
 */
function renderChildren(h, element, parent) {
  const layout = layouts[element.layout];
  if (layout) {
    return layout.call(this, h, element, parent);
  }
  return layoutIsNotFound.call(this);
}

function layoutIsNotFound() {
  throw new Error(`没有与${this.element.layout}匹配的layout`);
}

export default {
  name: "designItem",
  components: {
    render,
    draggable,
    dynamicTable,
    dynamicTableItem,
    fancyTable,
    fancyTableItem,
  },
  props: {
    model: {
      type: Object,
      default: {},
    },
    activeItem: {
      type: Object,
      default: {},
    },
  },
  data() {
    return {
      activeComponent: this.activeItem,
    };
  },
  render(h) {
    const layout = layouts[this.model.layout];
    if (layout) {
      return layout.call(this, h, this.model);
    }
    return layoutIsNotFound.call(this);
  },
  methods: {
    handlerAdd(evt, item, row) {
      if (evt.pullMode === "clone") {
        if (
          !(
            evt.to.className.indexOf("row-drag") > -1 &&
            this.activeItem.compType === "row"
          )
        ) {
          item.list.splice(evt.newIndex, 0, this.activeItem);
        }
      }
      /**
       *
       * else{
        const dragComp = evt.clone.lastElementChild.attributes.getNamedItem("comptype").value;
        console.log(dragComp)
        if(dragComp==='row'){  //防止row嵌套
          const newIndex = evt.newIndex;
          const oldIndex = evt.oldIndex;
          const rowItem  = item.list[newIndex];
          item.list.splice(newIndex,1);
          this.$message.error('布局组件不允许被嵌套！');
          this.$emit('rowItemRollBack',rowItem,oldIndex);  //还原到原先的列表中
          return false;
        }
      }
       */
    },
    /**
     * 动态表单
     */
    handlerDynamicAdd(evt, item) {
      if (evt.pullMode === "clone") {
        if (dynamicTableAllowedItems.includes(this.activeItem.compType)) {
          item.columns.splice(evt.newIndex, 0, this.activeItem);
        } else {
          this.$message.error("该组件不允许被放入动态表格内！");
        }
      } else {
        if (evt.item.className.indexOf("el-row") > -1) {
          //防止row嵌套
          const newIndex = evt.newIndex;
          const oldIndex = evt.oldIndex;
          const rowItem = item.columns[newIndex];
          item.columns.splice(newIndex, 1);
          this.$message.error("布局组件不允许放入动态表格！");
          this.$emit("rowItemRollBack", rowItem, oldIndex); //还原到原先的列表中
          return false;
        }
      }
    },
    handlerTableAdd(evt, td) {
      if (evt.pullMode === "clone") {
        if (!tableAllowedItems.includes(this.activeItem.compType)) {
          td.columns.splice(evt.newIndex, 0, this.activeItem);
        } else {
          this.$message.error("该组件不允许被放入表格内！");
        }
      }
    },
    handlerCopyItem(evt, element, index) {
      const item = element.columns[index];
      const clone = JSON.parse(JSON.stringify(item));
      let uId = "fd_" + getSimpleId();
      clone.id = uId;
      clone._id = uId;
      element.columns.push(clone);
    },
    handlerDeleteItem(evt, element, index) {
      element.columns.splice(index, 1);
    },
  },
};
</script>
